package com.vegetable.modules.service.stock.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.utils.Constant.StockFlowType;
import com.vegetable.modules.entity.stock.Stock;
import com.vegetable.modules.entity.stock.StockStatistics;
import com.vegetable.modules.entity.stock.po.StockFlowQueryPO;
import com.vegetable.modules.entity.stock.po.StockStatisticsQueryPO;
import com.vegetable.modules.entity.stock.to.StockFlowDTO;
import com.vegetable.modules.mapper.stock.StockMapper;
import com.vegetable.modules.mapper.stock.StockStatisticsMapper;
import com.vegetable.modules.service.stock.IStockFlowService;
import com.vegetable.modules.service.stock.IStockStatisticsService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存表 服务类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-21
 */
@Slf4j
@Service
@AllArgsConstructor
public class StockStatisticsServiceImpl extends ServiceImpl<StockStatisticsMapper, StockStatistics> implements IStockStatisticsService {

    @Resource
    private StockMapper stockMapper;
    @Resource
    private IStockFlowService stockFlowService;
    @Resource
    private StockStatisticsMapper stockStatisticsMapper;
    @Override
    @Scheduled(cron = "0 0 1 * * ?")
    public void initStockStatistics() {
        log.info("开始统计库存开始信息...");
        // 查询当前日期库存里的商品列表
        IPage page = new Page();
        page.setCurrent(1);
        page.setSize(Long.MAX_VALUE);
        IPage<Stock> stockPage = stockMapper.stockGroupBy(page, new HashMap<>());
        List<Stock> stockList = stockPage.getRecords();
        if(CollectionUtil.isEmpty(stockList)){
            log.info("当前库存为空");
            return;
        }
        Date createTime = new Date();
        for (Stock stock : stockList){
            StockStatistics ss = new StockStatistics();
            ss.setInitialCost(stock.getCost());
            ss.setInitialNumber(stock.getNumber());
            BeanUtils.copyProperties(stock, ss);
            ss.setCreateTime(createTime);
            // 记录
            stockStatisticsMapper.insert(ss);
        }
        log.info("统计库存信息结束...");
    }

    @Scheduled(cron = "0 50 23 * * ?")
    @Override
    public void balanceStockStatistics() {
        log.info("开始统计库存结余信息...");
        // 查询全部库存
        // 查询当前日期库存里的商品列表
        IPage page = new Page();
        page.setCurrent(1);
        page.setSize(Long.MAX_VALUE);
        IPage<Stock> stockPage = stockMapper.stockGroupBy(page, new HashMap<>());
        List<Stock> stockList = stockPage.getRecords();
        if(CollectionUtil.isEmpty(stockList)){
            log.info("当前库存为空");
            return;
        }
        // 库存商品id集合
        List<Long> commodityIds = stockList.stream().map(stock -> stock.getCommodityId()).collect(Collectors.toList());
        // 分别计算当天商品的出入库情况
        StockFlowQueryPO po = new StockFlowQueryPO();
        po.setCommodityIds(commodityIds);
        po.setStartTime(DateUtil.beginOfDay(DateUtil.yesterday()));
        po.setEndTime(DateUtil.beginOfDay(new Date()));
        IPage<StockFlowDTO> flowIPage = stockFlowService.stockFlowList(po);
        List<StockFlowDTO> flowList = flowIPage.getRecords();
        if(CollectionUtil.isEmpty(flowList)){
            log.info("出入库流水为空为空");
            return;
        }
        for(Stock stock : stockList){
            // 商品ID
            Long commodityId = stock.getCommodityId();
            // 规格ID
            Long specsId = stock.getSpecsId();
            List<StockFlowDTO> flows = flowList.stream().filter(flow -> flow.getCommodityId().equals(commodityId)).
                    filter(flow -> specsId.equals(flow.getSpecsId())).collect(Collectors.toList());
            // 入库流水
            List<StockFlowDTO> inFlows = flows.stream().filter(flow -> StockFlowType.isInType(flow.getOrderType())).
                    collect(Collectors.toList());
            // 出库流水
            List<StockFlowDTO> outFlows = flows.stream().
                    filter(flow -> !StockFlowType.isInType(flow.getOrderType())).collect(Collectors.toList());
            QueryWrapper<StockStatistics> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("commodity_id", commodityId);
            queryWrapper.eq("specs_id", specsId);
            queryWrapper.eq("create_time",  DateUtil.today());
            StockStatistics statistics = stockStatisticsMapper.selectOne(queryWrapper);
            if(Objects.isNull(statistics)){
                // 如果是空，说明是新商品
                StockStatistics ss = new StockStatistics();
                ss.setInitialCost(stock.getCost());
                ss.setInitialNumber(stock.getNumber());
                ss.setBalanceNumber(stock.getNumber());
                ss.setBalanceCost(stock.getCost());
                ss.setInNumber(inFlows.stream().map(flow -> flow.getNum()).reduce(BigDecimal.ZERO, BigDecimal::add));
                ss.setInCost(BigDecimal.valueOf(inFlows.stream().mapToDouble(flow -> flow.getCost().doubleValue()).sum()));
                ss.setOutNumber(outFlows.stream().map(flow -> flow.getNum()).reduce(BigDecimal.ZERO, BigDecimal::add));
                ss.setOutCost(BigDecimal.valueOf(outFlows.stream().mapToDouble(flow -> flow.getCost().doubleValue()).sum()));
                BeanUtils.copyProperties(stock, ss);
                ss.setCreateTime(new Date());
                // 记录
                stockStatisticsMapper.insert(ss);
            }else {
                statistics.setBalanceNumber(stock.getNumber());
                statistics.setBalanceCost(stock.getCost());
                statistics.setInNumber(inFlows.stream().map(flow -> flow.getNum()).reduce(BigDecimal.ZERO, BigDecimal::add));
                statistics.setInCost(BigDecimal.valueOf(inFlows.stream().mapToDouble(flow -> flow.getCost().doubleValue()).sum()));
                statistics.setOutNumber(outFlows.stream().map(flow -> flow.getNum()).reduce(BigDecimal.ZERO, BigDecimal::add));
                statistics.setOutCost(BigDecimal.valueOf(outFlows.stream().mapToDouble(flow -> flow.getCost().doubleValue()).sum()));
                stockStatisticsMapper.updateById(statistics);
            }
        }
        log.info("统计库存结余结束...");
    }

    @Override
    public IPage<StockStatistics> stockStatisticsList(StockStatisticsQueryPO po) {
        Page<StockStatistics> page = new Page<>(po.getPage(), po.getLIMIT());
        QueryWrapper<StockStatistics> queryWrapper = new QueryWrapper<>();
        // 商品名模糊查询
        queryWrapper.gt(Objects.nonNull(po.getCreateTimeStart()), "create_time", po.getCreateTimeStart());
        // 仓库名模糊查询
        queryWrapper.lt(Objects.nonNull(po.getCreateTimeEnd()), "create_time", po.getCreateTimeEnd());
        queryWrapper.orderByDesc("id");
        IPage<StockStatistics> result = stockStatisticsMapper.selectPage(page, queryWrapper);
        return result;
    }
}
